//
//  PMDampedRotarySpring.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/30/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMConstraint for representing damped rotary springs. 
 * PMDampedRotarySprings are used to bind the rotation of two rigid bodies in a 
 * flexible manner. PMDampedRotarySprings are like PMDampedSprings that supply
 * torque rather than force. The properties that define a PMDampedRotarySpring
 * are also much like that of a PMDampedSpring, with the exception of using a 
 * rest angle rather than rest length.
 */

#import "PMDampedRotarySpring.h"
#import "PMBody.h"


@implementation PMDampedRotarySpring


#pragma mark -
#pragma mark Init

/**
 * Returns a PMDampedRotarySpring object initialized to bind two given rigid bodies
 * with a given rest angle, stiffness, and damping. 
 */
- (id)initWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody restAngle:(PMFloat)restAngle stiffness:(PMFloat)stiffness damping:(PMFloat)damping {
	if (![super init])
	return nil;

	// allocate and initialize cpConstraint
	constraint = cpDampedRotarySpringNew(aBody.cpBody, otherBody.cpBody, 
										 restAngle, stiffness, damping);

	// set body references
	self.bodyA = aBody;
	self.bodyB = otherBody;

	// reference this PMConstraint object with cpConstraint's data pointer
	// this is for internal use
	constraint->data = self;

	return self;
}


#pragma mark Convenience

/**
 * Creates and returns a PMDampedRotarySpring object initialized to bind two given 
 * rigid bodies with a given rest angle, stiffness, and damping. 
 */
+ (PMDampedRotarySpring *)dampedRotarySpringWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody restAngle:(PMFloat)restAngle stiffness:(PMFloat)stiffness damping:(PMFloat)damping {
	return [[[PMDampedRotarySpring alloc] initWithBodyA:aBody 
												  bodyB:otherBody 
											  restAngle:restAngle 
											  stiffness:stiffness 
												damping:damping] autorelease];
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the relative angle between the receiver's bodies when at rest.
 */
- (PMFloat)restAngle {
	return cpDampedRotarySpringGetRestAngle(constraint);
}

/**
 * Returns the receiver's spring constant. This is the same as the receiver's 
 * stiffness.
 */
- (PMFloat)springConst {
	return [self stiffness];
}

/**
 * Returns the receiver's stiffness. This is the same as the receivers spring
 * constant.
 */
- (PMFloat)stiffness {
	return cpDampedRotarySpringGetStiffness(constraint);
}

/**
 * Returns the amount of damping applied to the receiver.
 */
- (PMFloat)damping {
	return cpDampedRotarySpringGetDamping(constraint);
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the relative angle between the receiver's bodies when at rest to a given 
 * value.
 */
- (void)setRestAngle:(PMFloat)restAngle {
	cpDampedRotarySpringSetRestAngle(constraint, restAngle);
}	

/**
 * Sets the receiver's spring constant to a given value. This is the same as
 * setting the receiver's stiffness.
 */
- (void)setSpringConst:(PMFloat)springConst {
	[self setStiffness:springConst];
}

/**
 * Sets the receiver's stiffness to a given value. This is the same as setting
 * the receiver's spring constant.
 */
- (void)setStiffness:(PMFloat)stiffness {
	cpDampedRotarySpringSetStiffness(constraint, stiffness);
}

/**
 * Sets the amount of damping applied to the receiver to a given value.
 */
- (void)setDamping:(PMFloat)damping {
	cpDampedRotarySpringSetDamping(constraint, damping);
}

@end
